/*****************************************************************************
 *  Copyright Statement:
 *  --------------------
 *  This software is protected by Copyright and the information contained
 *  herein is confidential. The software may not be copied and the information
 *  contained herein may not be used or disclosed except with the written
 *  permission of MediaTek Inc. (C) 2005
 *
 *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
 *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
 *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
 *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
 *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
 *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
 *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
 *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
 *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
 *
 *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
 *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
 *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
 *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
 *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
 *
 *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
 *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
 *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
 *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
 *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
 *
 *****************************************************************************/

/*****************************************************************************
 *
 * Filename:
 * ---------
 *    idp_val.c
 *
 * Project:
 * --------
 *    MAUI
 *
 * Description:
 * ------------
 *    The adaptation layer for video related legacy API functions.
 *
 * Author:
 * -------
 * -------
 *
 *============================================================================
 *             HISTORY
 * Below this line, this part is controlled by ClearCase. DO NOT MODIFY!!
 *------------------------------------------------------------------------------
 * $Log$
 *
 * 12 29 2010 ct.fang
 * removed!
 * .
 *
 * 08 10 2010 ct.fang
 * removed!
 * .
 *
 * 08 05 2010 ct.fang
 * removed!
 * .
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * Fix build warnings
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 * removed!
 * removed!
 * 
 *
 *
 * 
 *------------------------------------------------------------------------------
 * Upper this line, this part is controlled by ClearCase. DO NOT MODIFY!!
 *============================================================================
 ****************************************************************************/

#define THIS_FILE_BELONGS_TO_IMAGE_DATA_PATH_MODULE_INTERNAL

#include <drv_comm.h>

#if !defined(DRV_IDP_OLD_DESIGN)

#include <idp_val.h>

#ifdef TV_OUT_SUPPORT
#include <tv_out.h>
#endif

#include <idp_core_internal.h>
#include <idp_video_decode.h>
#include <idp_video_editor_decode.h>
#include <idp_video_editor_encode.h>
#include <idp_video_call_decode.h>
#include <img_common_enum.h>

/* =================================================
 *                Video decode
 * ================================================= */
#ifdef DRV_IDP_6238_SERIES

static kal_bool video_decode_have_config_lcd = KAL_FALSE;

#if defined(TV_OUT_SUPPORT)
static kal_bool video_decode_have_config_tvout = KAL_FALSE;
#endif // #if defined(TV_OUT_SUPPORT)

static kal_bool video_decode_trigger_lcd_this_time = KAL_FALSE;

#if defined(TV_OUT_SUPPORT)
static kal_bool video_decode_trigger_tvout = KAL_FALSE;
#endif // #if defined(TV_OUT_SUPPORT)

static kal_uint32 video_decode_triggered_lcd_id_this_time = 0;

static void
src_clip_2_dst_clip_hori(img_rot_angle_enum_t const rot_angle,
                         kal_uint32 const src_width,
                         kal_uint32 const tar_width,
                         kal_uint32 const src_x1,
                         kal_uint32 const src_x2,
                         kal_uint32 * const dst_x1,
                         kal_uint32 * const dst_x2)
{
  if (NULL == dst_x1)
  {
    ASSERT(0);
  }
  if (NULL == dst_x2)
  {
    ASSERT(0);
  }
  
  {
    kal_uint32 const tar_x1 = ((src_x1 * tar_width) / src_width);
    // [MAUI_01207646]
    kal_uint32 const tar_x2 = (((src_x2 + 1) * tar_width) / src_width) - 1;
    
    (*dst_x1) = tar_x1;
    (*dst_x2) = tar_x2;
  }
}

static void
src_clip_2_dst_clip_vert(img_rot_angle_enum_t const rot_angle,
                         kal_uint32 const src_height,
                         kal_uint32 const tar_height,
                         kal_uint32 const src_y1,
                         kal_uint32 const src_y2,
                         kal_uint32 * const dst_y1,
                         kal_uint32 * const dst_y2)
{
  if (NULL == dst_y1)
  {
    ASSERT(0);
  }
  if (NULL == dst_y2)
  {
    ASSERT(0);
  }
  
  {
    kal_uint32 const tar_y1 = ((src_y1 * tar_height) / src_height);
    // [MAUI_01207646]
    kal_uint32 const tar_y2 = (((src_y2 + 1) * tar_height) / src_height) - 1;
    
    (*dst_y1) = tar_y1;
    (*dst_y2) = tar_y2;
  }
}

static kal_bool g_idp_val_video_decode_is_vp7 = KAL_FALSE;

kal_bool
idp_val_video_decode_is_vp7(
    MP4DEC_IMGPATH_STRUCT const * const data_input)
{
  if (KAL_FALSE == data_input->force_lcd_hw_trigger)
  {
    return KAL_TRUE;
  }
  else
  {
    return KAL_FALSE;
  }
}

kal_bool
idp_val_video_decode_configurable(kal_uint32 const key,
                                  kal_uint32 const idp_int_addr,
                                  kal_uint32 const idp_int_size,
                                  kal_uint32 const idp_ext_addr,
                                  kal_uint32 const idp_ext_size,
                                  kal_uint32 const video_src_width_with_dummy,
                                  kal_uint32 const video_src_height_with_dummy,
                                  kal_uint32 const clip_left,
                                  kal_uint32 const clip_right,
                                  kal_uint32 const clip_top,
                                  kal_uint32 const clip_bottom,
                                  kal_uint32 const y_address,
                                  kal_uint32 const u_address,
                                  kal_uint32 const v_address,
                                  kal_bool   const b_quant,
                                  kal_uint32 const quant_addr,
                                  kal_bool   const FMT_4X4,
                                  MP4DEC_IMGPATH_STRUCT const * const data_input)
{
#if defined(__MTK_TARGET__)
  kal_bool result;
  kal_uint32 dst_clip_x1;
  kal_uint32 dst_clip_x2;
  kal_uint32 dst_clip_y1;
  kal_uint32 dst_clip_y2;
  kal_uint32 video_target_width_with_dummy;
  kal_uint32 video_target_height_with_dummy;  
  kal_uint32 real_video_display_width; /* The display target width after rotation */
  kal_uint32 real_video_display_height; /* The display target height after rotation */
  kal_uint32 real_video_clip_left; /* the clip_left after resizing and rotation. */
  kal_uint32 real_video_clip_right; /* the clip_right after resizing and rotation. */
  kal_uint32 real_video_clip_top; /* the clip_top after resizing and rotation. */
  kal_uint32 real_video_clip_bottom; /* the clip_bottom after resizing and rotation. */
  kal_uint32 const src_clip_width = (clip_right - clip_left + 1);
  kal_uint32 const src_clip_height = (clip_bottom - clip_top + 1);
  kal_uint32 video_target_width_wo_dummy;
  kal_uint32 video_target_height_wo_dummy;
  
  ASSERT(clip_left <= clip_right);
  ASSERT(clip_top <= clip_bottom);
  ASSERT(clip_right < video_src_width_with_dummy);
  ASSERT(clip_bottom < video_src_height_with_dummy);

  // [MAUI_02601232] Block all video clips with src clipping size <= 15...
  if ((16 > src_clip_width) || (16 > src_clip_height))
  {
    return KAL_FALSE;
  }
  
  g_idp_val_video_decode_is_vp7 = idp_val_video_decode_is_vp7(data_input);
  
#if defined(IDP_VIDEO_DECODE_ENLARGE_FOR_TV)
  if (KAL_TRUE == g_idp_val_video_decode_is_vp7)
  {
    video_target_width_wo_dummy = IDP_VP7_MIDDLE_BUFFER_WIDTH;
    video_target_height_wo_dummy = IDP_VP7_MIDDLE_BUFFER_HEIGHT;
  }
  else
  {
#endif
    switch (data_input->rotate_angle)
    {
    case IMG_ROT_ANGLE_0:
    case IMG_ROT_ANGLE_180:
      video_target_width_wo_dummy = data_input->disp_width;
      video_target_height_wo_dummy = data_input->disp_height;
      break;
    
    case IMG_ROT_ANGLE_90:
    case IMG_ROT_ANGLE_270:
      video_target_width_wo_dummy = data_input->disp_height;
      video_target_height_wo_dummy = data_input->disp_width;
      break;
    
    default:
      ASSERT(0);
      video_target_width_wo_dummy = 0;
      video_target_height_wo_dummy = 0;
      break;
    }
#if defined(IDP_VIDEO_DECODE_ENLARGE_FOR_TV)
  }
#endif

  // [MAUI_01245490]
  video_target_width_with_dummy = (((kal_uint32)(video_target_width_wo_dummy) * 
                                    (kal_uint32)(video_src_width_with_dummy) + 
                                    (kal_uint32)(src_clip_width) - 1) /
                                   (kal_uint32)(src_clip_width));
  video_target_height_with_dummy = (((kal_uint32)(video_target_height_wo_dummy) *
                                     (kal_uint32)(video_src_height_with_dummy) + 
                                     (kal_uint32)(src_clip_height) - 1) /
                                    (kal_uint32)(src_clip_height));
  
  for (;;)
  {
    src_clip_2_dst_clip_hori(data_input->rotate_angle,
                             video_src_width_with_dummy,
                             video_target_width_with_dummy,
                             clip_left,
                             clip_right,
                             &dst_clip_x1,
                             &dst_clip_x2);
    
    if ((dst_clip_x2 - dst_clip_x1 + 1) < video_target_width_wo_dummy)
    {
      ++video_target_width_with_dummy;
      continue;
    }
    else if ((dst_clip_x2 - dst_clip_x1 + 1) > video_target_width_wo_dummy)
    {
      dst_clip_x2 = (dst_clip_x1 + video_target_width_wo_dummy - 1);
      break;
    }
    else
    {
      break;
    }
  }
  
  for (;;)
  {
    src_clip_2_dst_clip_vert(data_input->rotate_angle,
                             video_src_height_with_dummy,
                             video_target_height_with_dummy,
                             clip_top,
                             clip_bottom,
                             &dst_clip_y1,
                             &dst_clip_y2);
    
    if ((dst_clip_y2 - dst_clip_y1 + 1) < video_target_height_wo_dummy)
    {
      ++video_target_height_with_dummy;
      continue;
    }
    else if ((dst_clip_y2 - dst_clip_y1 + 1) > video_target_height_wo_dummy)
    {
      dst_clip_y2 = (dst_clip_y1 + video_target_height_wo_dummy - 1);
      break;
    }
    else
    {
      break;
    }
  }
  
#if defined(IDP_VIDEO_DECODE_ENLARGE_FOR_TV)
  if (KAL_TRUE == g_idp_val_video_decode_is_vp7)
  {
    real_video_display_width = data_input->disp_width;
    real_video_display_height = data_input->disp_height;
    real_video_clip_left = dst_clip_x1;
    real_video_clip_right = dst_clip_x2;
    real_video_clip_top = dst_clip_y1;
    real_video_clip_bottom = dst_clip_y2;
  }
  else
  {
#endif
    switch (data_input->rotate_angle)
    {
    case IMG_ROT_ANGLE_0:
      real_video_display_width = video_target_width_with_dummy;
      real_video_display_height = video_target_height_with_dummy;
      real_video_clip_left = dst_clip_x1;
      real_video_clip_right = dst_clip_x2;
      real_video_clip_top = dst_clip_y1;
      real_video_clip_bottom = dst_clip_y2;
      break;
    
    case IMG_ROT_ANGLE_180:
      real_video_display_width = video_target_width_with_dummy;
      real_video_display_height = video_target_height_with_dummy;
      real_video_clip_left = (real_video_display_width - 1 - dst_clip_x2);
      real_video_clip_right = (real_video_display_width - 1 - dst_clip_x1);
      real_video_clip_top = (real_video_display_height - 1 - dst_clip_y2);
      real_video_clip_bottom = (real_video_display_height - 1 - dst_clip_y1);
      break;

    case IMG_ROT_ANGLE_90:
      real_video_display_width = video_target_height_with_dummy;
      real_video_display_height = video_target_width_with_dummy;
      real_video_clip_left = (real_video_display_width - 1 - dst_clip_y2);
      real_video_clip_right = (real_video_display_width - 1 - dst_clip_y1);
      real_video_clip_top = dst_clip_x1;
      real_video_clip_bottom = dst_clip_x2;
      break;

    case IMG_ROT_ANGLE_270:
      real_video_display_width = video_target_height_with_dummy;
      real_video_display_height = video_target_width_with_dummy;
      real_video_clip_left = dst_clip_y1;
      real_video_clip_right = dst_clip_y2;
      real_video_clip_top = (real_video_display_height - 1 - dst_clip_x2);
      real_video_clip_bottom = (real_video_display_height - 1 - dst_clip_x1);
      break;
    
    default:
      ASSERT(0);
      real_video_display_width = 0;
      real_video_display_height = 0;
      real_video_clip_left = 0;
      real_video_clip_right = 0;
      real_video_clip_top = 0;
      real_video_clip_bottom = 0; 
      break;
    }
#if defined(IDP_VIDEO_DECODE_ENLARGE_FOR_TV)
  }
#endif
  
  result = idp_video_decode_configurable(
      key,
    
      IDP_VIDEO_DECODE_INTMEM_START_ADDRESS, idp_int_addr,
      IDP_VIDEO_DECODE_INTMEM_SIZE, idp_int_size,
      IDP_VIDEO_DECODE_EXTMEM_START_ADDRESS, idp_ext_addr,
      IDP_VIDEO_DECODE_EXTMEM_SIZE, idp_ext_size,
    
      IDP_VIDEO_DECODE_SRC_WIDTH, video_src_width_with_dummy,
      IDP_VIDEO_DECODE_SRC_HEIGHT, video_src_height_with_dummy,
#if defined(IDP_VIDEO_DECODE_ENLARGE_FOR_TV)
      IDP_VIDEO_DECODE_TARGET_WIDTH_FOR_TVOUT, video_target_width_with_dummy,
      IDP_VIDEO_DECODE_TARGET_HEIGHT_FOR_TVOUT, video_target_height_with_dummy,
#else
      IDP_VIDEO_DECODE_TARGET_WIDTH_FOR_TVOUT, real_video_display_width,
      IDP_VIDEO_DECODE_TARGET_HEIGHT_FOR_TVOUT, real_video_display_height,
#endif
      IDP_VIDEO_DECODE_TARGET_WIDTH, real_video_display_width,
      IDP_VIDEO_DECODE_TARGET_HEIGHT, real_video_display_height,
    
      IDP_VIDEO_DECODE_ENABLE_CLIP, KAL_TRUE,
      IDP_VIDEO_DECODE_CLIP_LEFT, real_video_clip_left,
      IDP_VIDEO_DECODE_CLIP_RIGHT, real_video_clip_right,
      IDP_VIDEO_DECODE_CLIP_TOP, real_video_clip_top,
      IDP_VIDEO_DECODE_CLIP_BOTTOM, real_video_clip_bottom,
    
      IDP_VIDEO_DECODE_CONTRAST_LEVEL, data_input->contrast_level,
      IDP_VIDEO_DECODE_BRIGHTNESS_LEVEL, data_input->brightness_level, 
      IDP_VIDEO_DECODE_VIDEO_Y_BUFFER_ADDRESS, y_address,
      IDP_VIDEO_DECODE_VIDEO_U_BUFFER_ADDRESS, u_address,
      IDP_VIDEO_DECODE_VIDEO_V_BUFFER_ADDRESS, v_address,
#if defined(DRV_MP4_DEC_SUPPORT)
      IDP_VIDEO_DECODE_ENABLE_PITCH, data_input->image_pitch_mode,
      IDP_VIDEO_DECODE_BG_IMAGE_WIDTH, data_input->image_pitch_bytes, 
      IDP_VIDEO_DECODE_IMAGE_DATA_FORMAT, data_input->image_data_format, 
#endif
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS, data_input->lcd_buf_addr,
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS_2, data_input->lcd_buf_addr_2,
      IDP_VIDEO_DECODE_TRIGGER_LCD, KAL_TRUE,
      IDP_VIDEO_DECODE_FORCE_LCD_HW_TRIGGER, data_input->force_lcd_hw_trigger,
    
      IDP_VIDEO_DECODE_ROT_ANGLE, data_input->rotate_angle,
      IDP_VIDEO_DECODE_SRC_FMT_4X4, FMT_4X4,
      IDP_VIDEO_DECODE_ENABLE_MP4DEBLK, b_quant,
      IDP_VIDEO_DECODE_MP4DEBLK_QUANT_BUF, quant_addr,
    
#if defined(__MTK_TARGET__)
      IDP_VIDEO_DECODE_RESIZER_U_VALUE, 8,
      IDP_VIDEO_DECODE_RESIZER_V_VALUE, 15,
#endif
    
      0);
  if (KAL_FALSE == result)
  {
    return KAL_FALSE;
  }
  else
  {
    return KAL_TRUE;
  }
#else
  return KAL_TRUE;
#endif
}

kal_bool
idp_val_video_decode_config(kal_uint32 const key,
                            kal_uint32 const idp_int_addr,
                            kal_uint32 const idp_int_size,
                            kal_uint32 const idp_ext_addr,
                            kal_uint32 const idp_ext_size,
                            kal_uint32 const video_src_width_with_dummy,
                            kal_uint32 const video_src_height_with_dummy,
                            kal_uint32 const clip_left,
                            kal_uint32 const clip_right,
                            kal_uint32 const clip_top,
                            kal_uint32 const clip_bottom,
                            kal_uint32 const y_address,
                            kal_uint32 const u_address,
                            kal_uint32 const v_address,
                            kal_bool   const b_quant,
                            kal_uint32 const quant_addr,
                            kal_bool   const FMT_4X4,
                            MP4DEC_IMGPATH_STRUCT const * const data_input)
{
  kal_bool result;
  kal_uint32 dst_clip_x1;
  kal_uint32 dst_clip_x2;
  kal_uint32 dst_clip_y1;
  kal_uint32 dst_clip_y2;
  kal_uint32 video_target_width_with_dummy;
  kal_uint32 video_target_height_with_dummy;  
  kal_uint32 real_video_display_width; /* The display target width after rotation */
  kal_uint32 real_video_display_height; /* The display target height after rotation */
  kal_uint32 real_video_clip_left; /* the clip_left after resizing and rotation. */
  kal_uint32 real_video_clip_right; /* the clip_right after resizing and rotation. */
  kal_uint32 real_video_clip_top; /* the clip_top after resizing and rotation. */
  kal_uint32 real_video_clip_bottom; /* the clip_bottom after resizing and rotation. */
  kal_uint32 const src_clip_width = (clip_right - clip_left + 1);
  kal_uint32 const src_clip_height = (clip_bottom - clip_top + 1);
  kal_uint32 video_target_width_wo_dummy;
  kal_uint32 video_target_height_wo_dummy;

  ASSERT(clip_left <= clip_right);
  ASSERT(clip_top <= clip_bottom);
  ASSERT(clip_right < video_src_width_with_dummy);
  ASSERT(clip_bottom < video_src_height_with_dummy);

  // [MAUI_02601232] Block all video clips with src clipping size <= 15...
  if ((16 > src_clip_width) || (16 > src_clip_height))
  {
    return KAL_FALSE;
  }
  
  g_idp_val_video_decode_is_vp7 = idp_val_video_decode_is_vp7(data_input);
  
#if defined(IDP_VIDEO_DECODE_ENLARGE_FOR_TV)
  if (KAL_TRUE == g_idp_val_video_decode_is_vp7)
  {
    video_target_width_wo_dummy = IDP_VP7_MIDDLE_BUFFER_WIDTH;
    video_target_height_wo_dummy = IDP_VP7_MIDDLE_BUFFER_HEIGHT;
  }
  else
  {
#endif
    switch (data_input->rotate_angle)
    {
    case IMG_ROT_ANGLE_0:
    case IMG_ROT_ANGLE_180:
      video_target_width_wo_dummy = data_input->disp_width;
      video_target_height_wo_dummy = data_input->disp_height;
      break;
    
    case IMG_ROT_ANGLE_90:
    case IMG_ROT_ANGLE_270:
      video_target_width_wo_dummy = data_input->disp_height;
      video_target_height_wo_dummy = data_input->disp_width;
      break;
    
    default:
      ASSERT(0);
      video_target_width_wo_dummy = 0;
      video_target_height_wo_dummy = 0;
      break;
    }
#if defined(IDP_VIDEO_DECODE_ENLARGE_FOR_TV)
  }
#endif

  // [MAUI_01245490]
  video_target_width_with_dummy = (((kal_uint32)(video_target_width_wo_dummy) *
                                    (kal_uint32)(video_src_width_with_dummy) + 
                                    (kal_uint32)(src_clip_width) - 1) /
                                   (kal_uint32)(src_clip_width));
  video_target_height_with_dummy = (((kal_uint32)(video_target_height_wo_dummy) *
                                     (kal_uint32)(video_src_height_with_dummy) + 
                                     (kal_uint32)(src_clip_height) - 1) /
                                    (kal_uint32)(src_clip_height));
  
  for (;;)
  {
    src_clip_2_dst_clip_hori(data_input->rotate_angle,
                             video_src_width_with_dummy,
                             video_target_width_with_dummy,
                             clip_left,
                             clip_right,
                             &dst_clip_x1,
                             &dst_clip_x2);
    
    if ((dst_clip_x2 - dst_clip_x1 + 1) < video_target_width_wo_dummy)
    {
      ++video_target_width_with_dummy;
      continue;
    }
    else if ((dst_clip_x2 - dst_clip_x1 + 1) > video_target_width_wo_dummy)
    {
      dst_clip_x2 = (dst_clip_x1 + video_target_width_wo_dummy - 1);
      break;
    }
    else
    {
      break;
    }
  }
  
  for (;;)
  {
    src_clip_2_dst_clip_vert(data_input->rotate_angle,
                             video_src_height_with_dummy,
                             video_target_height_with_dummy,
                             clip_top,
                             clip_bottom,
                             &dst_clip_y1,
                             &dst_clip_y2);
    
    if ((dst_clip_y2 - dst_clip_y1 + 1) < video_target_height_wo_dummy)
    {
      ++video_target_height_with_dummy;
      continue;
    }
    else if ((dst_clip_y2 - dst_clip_y1 + 1) > video_target_height_wo_dummy)
    {
      dst_clip_y2 = (dst_clip_y1 + video_target_height_wo_dummy - 1);
      break;
    }
    else
    {
      break;
    }
  }
  
#if defined(IDP_VIDEO_DECODE_ENLARGE_FOR_TV)
  if (KAL_TRUE == g_idp_val_video_decode_is_vp7)
  {
    real_video_display_width = data_input->disp_width;
    real_video_display_height = data_input->disp_height;
    real_video_clip_left = dst_clip_x1;
    real_video_clip_right = dst_clip_x2;
    real_video_clip_top = dst_clip_y1;
    real_video_clip_bottom = dst_clip_y2;
  }
  else
  {
#endif
    switch (data_input->rotate_angle)
    {
    case IMG_ROT_ANGLE_0:
      real_video_display_width = video_target_width_with_dummy;
      real_video_display_height = video_target_height_with_dummy;
      real_video_clip_left = dst_clip_x1;
      real_video_clip_right = dst_clip_x2;
      real_video_clip_top = dst_clip_y1;
      real_video_clip_bottom = dst_clip_y2;
      break;
    
    case IMG_ROT_ANGLE_180:
      real_video_display_width = video_target_width_with_dummy;
      real_video_display_height = video_target_height_with_dummy;
      real_video_clip_left = (real_video_display_width - 1 - dst_clip_x2);
      real_video_clip_right = (real_video_display_width - 1 - dst_clip_x1);
      real_video_clip_top = (real_video_display_height - 1 - dst_clip_y2);
      real_video_clip_bottom = (real_video_display_height - 1 - dst_clip_y1);
      break;
    
    case IMG_ROT_ANGLE_90:
      real_video_display_width = video_target_height_with_dummy;
      real_video_display_height = video_target_width_with_dummy;
      real_video_clip_left = (real_video_display_width - 1 - dst_clip_y2);
      real_video_clip_right = (real_video_display_width - 1 - dst_clip_y1);
      real_video_clip_top = dst_clip_x1;
      real_video_clip_bottom = dst_clip_x2;
      break;
    
    case IMG_ROT_ANGLE_270:
      real_video_display_width = video_target_height_with_dummy;
      real_video_display_height = video_target_width_with_dummy;
      real_video_clip_left = dst_clip_y1;
      real_video_clip_right = dst_clip_y2;
      real_video_clip_top = (real_video_display_height - 1 - dst_clip_x2);
      real_video_clip_bottom = (real_video_display_height - 1 - dst_clip_x1);
      break;
    
    default:
      ASSERT(0);
      real_video_display_width = 0;
      real_video_display_height = 0;
      real_video_clip_left = 0;
      real_video_clip_right = 0;
      real_video_clip_top = 0;
      real_video_clip_bottom = 0; 
      break;
    }
#if defined(IDP_VIDEO_DECODE_ENLARGE_FOR_TV)
  }
#endif
  
  result = idp_video_decode_config(
      key,
    
      IDP_VIDEO_DECODE_INTMEM_START_ADDRESS, idp_int_addr,
      IDP_VIDEO_DECODE_INTMEM_SIZE, idp_int_size,
      IDP_VIDEO_DECODE_EXTMEM_START_ADDRESS, idp_ext_addr,
      IDP_VIDEO_DECODE_EXTMEM_SIZE, idp_ext_size,
    
      IDP_VIDEO_DECODE_SRC_WIDTH, video_src_width_with_dummy,
      IDP_VIDEO_DECODE_SRC_HEIGHT, video_src_height_with_dummy,
#if defined(IDP_VIDEO_DECODE_ENLARGE_FOR_TV)
      IDP_VIDEO_DECODE_TARGET_WIDTH_FOR_TVOUT, video_target_width_with_dummy,
      IDP_VIDEO_DECODE_TARGET_HEIGHT_FOR_TVOUT, video_target_height_with_dummy,
#else
      IDP_VIDEO_DECODE_TARGET_WIDTH_FOR_TVOUT, real_video_display_width,
      IDP_VIDEO_DECODE_TARGET_HEIGHT_FOR_TVOUT, real_video_display_height,
#endif
      IDP_VIDEO_DECODE_TARGET_WIDTH, real_video_display_width,
      IDP_VIDEO_DECODE_TARGET_HEIGHT, real_video_display_height,
    
      IDP_VIDEO_DECODE_ENABLE_CLIP, KAL_TRUE,
      IDP_VIDEO_DECODE_CLIP_LEFT, real_video_clip_left,
      IDP_VIDEO_DECODE_CLIP_RIGHT, real_video_clip_right,
      IDP_VIDEO_DECODE_CLIP_TOP, real_video_clip_top,
      IDP_VIDEO_DECODE_CLIP_BOTTOM, real_video_clip_bottom,
    
      IDP_VIDEO_DECODE_CONTRAST_LEVEL, data_input->contrast_level,
      IDP_VIDEO_DECODE_BRIGHTNESS_LEVEL, data_input->brightness_level, 
      IDP_VIDEO_DECODE_VIDEO_Y_BUFFER_ADDRESS, y_address,
      IDP_VIDEO_DECODE_VIDEO_U_BUFFER_ADDRESS, u_address,
      IDP_VIDEO_DECODE_VIDEO_V_BUFFER_ADDRESS, v_address,
#if defined(DRV_MP4_DEC_SUPPORT)
      IDP_VIDEO_DECODE_ENABLE_PITCH, data_input->image_pitch_mode,
      IDP_VIDEO_DECODE_BG_IMAGE_WIDTH, data_input->image_pitch_bytes, 
      IDP_VIDEO_DECODE_IMAGE_DATA_FORMAT, data_input->image_data_format, 
#endif
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS, data_input->lcd_buf_addr,
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS_2, data_input->lcd_buf_addr_2,
      IDP_VIDEO_DECODE_TRIGGER_LCD, KAL_TRUE,
      IDP_VIDEO_DECODE_FORCE_LCD_HW_TRIGGER, data_input->force_lcd_hw_trigger,
    
      IDP_VIDEO_DECODE_ROT_ANGLE, data_input->rotate_angle,
      IDP_VIDEO_DECODE_SRC_FMT_4X4, FMT_4X4,
      IDP_VIDEO_DECODE_ENABLE_MP4DEBLK, b_quant,
      IDP_VIDEO_DECODE_MP4DEBLK_QUANT_BUF, quant_addr,
    
#if defined(__MTK_TARGET__)
      IDP_VIDEO_DECODE_RESIZER_U_VALUE, 8,
      IDP_VIDEO_DECODE_RESIZER_V_VALUE, 15,
#endif
    
      0);
  if (KAL_FALSE == result)
  {
    return KAL_FALSE;
  }
  
  // config lcd & tv
  {
    lcd_frame_update_struct lcd_data;
    
    memset(&lcd_data, 0, sizeof(lcd_data));
    
    // This path doesn't trigger LCD all the time.
    video_decode_trigger_lcd_this_time = KAL_TRUE;
    
    {
      if (KAL_FALSE == video_decode_have_config_lcd)
      {
        video_decode_triggered_lcd_id_this_time = data_input->lcd_data->lcd_id;
        
        {
          if (KAL_TRUE == g_idp_val_video_decode_is_vp7)
          {
            lcd_data.fb_update_mode = LCD_DIRECT_COUPLE_MODE;
#if defined(DRV_IDP_6238_SERIES)
            lcd_data.hw_trigger_src = LCD_HW_TRIGGER_IBW1;
#endif // #if defined(DRV_IDP_6238_SERIES)
          }
          else
          {
            lcd_data.fb_update_mode = LCD_HW_TRIGGER_MODE;
#if defined(DRV_IDP_6238_SERIES)
            lcd_data.hw_trigger_src = LCD_HW_TRIGGER_IRT1;
#endif // #if defined(DRV_IDP_6238_SERIES)
          }
          
          lcd_data.memory_output = KAL_FALSE;
          lcd_data.block_mode_flag = KAL_FALSE;
          lcd_data.lcd_block_mode_cb = NULL;
        }
        
        {
          lcd_data.module_id = data_input->lcd_data->module_id;
          lcd_data.lcd_id = data_input->lcd_data->lcd_id;
        
          lcd_data.lcm_start_x = data_input->lcd_data->lcm_start_x;
          lcd_data.lcm_start_y = data_input->lcd_data->lcm_start_y;
          lcd_data.lcm_end_x = data_input->lcd_data->lcm_end_x;
          lcd_data.lcm_end_y = data_input->lcd_data->lcm_end_y;
          
          lcd_data.roi_offset_x = data_input->lcd_data->roi_offset_x;
          lcd_data.roi_offset_y = data_input->lcd_data->roi_offset_y;
          
          lcd_data.update_layer = data_input->lcd_data->update_layer;
          lcd_data.hw_update_layer = data_input->lcd_data->hw_update_layer;
          
          lcd_data.roi_background_color = data_input->lcd_data->roi_background_color;
        }
        
#if defined(TV_OUT_SUPPORT) && defined(DRV_MP4_V2)
        video_decode_trigger_tvout = data_input->tv_output;
        
        if ((KAL_TRUE == data_input->tv_output) &&
            ((TV_OUTPUT_MODE1 == tv_output_config_data.tv_output_mode) ||
             (TV_OUTPUT_MODE4 == tv_output_config_data.tv_output_mode)))
        {
          // Config TV output through LCD.
          lcd_data.tv_output = KAL_TRUE;
          
          lcd_data.tv_output_width = data_input->lcd_data->tv_output_width;
          lcd_data.tv_output_height = data_input->lcd_data->tv_output_height;
          lcd_data.tv_output_offset_x = data_input->lcd_data->tv_output_offset_x;
          lcd_data.tv_output_offset_y = data_input->lcd_data->tv_output_offset_y;
          lcd_data.tv_output_frame_buffer1_address = data_input->tv_output_frame_buffer1_address;
          lcd_data.tv_output_frame_buffer2_address = data_input->tv_output_frame_buffer2_address;
          lcd_data.tv_output_frame_buffer_size = data_input->tv_output_frame_buffer_size;
          
          // Update TV output owner.
          tv_output_owner = TV_OUT_OWNER_MMI;
        }
        else
        {
          // TV output mode 2 & 3 don't use LCD.
          lcd_data.tv_output = KAL_FALSE;
        }
#else
        lcd_data.tv_output = KAL_FALSE;
#endif
        
        // Config LCD and start updating.
        lcd_fb_update(&lcd_data);
        
        video_decode_have_config_lcd = KAL_TRUE;
      }
    }
    
#if defined(TV_OUT_SUPPORT) && defined(DRV_MP4_V2)
    video_decode_trigger_tvout = data_input->tv_output;
    
    if ((KAL_TRUE == data_input->tv_output) &&
        ((TV_OUTPUT_MODE2 == tv_output_config_data.tv_output_mode) ||
         (TV_OUTPUT_MODE3 == tv_output_config_data.tv_output_mode)))
    {
      // TV output mode 2 & 3 don't use LCD, so that I have
      // to config it separatly.
      if (KAL_FALSE == video_decode_have_config_tvout)
      {
        // Update tv output owner.
        tv_output_owner = TV_OUT_OWNER_MP4_DEC;
        
        if (KAL_TRUE == g_idp_val_video_decode_is_vp7)
        {
          set_tv_output_data_format(TV_DATA_RGB565);
          set_tv_src_size(TV_OUT_OWNER_MP4_DEC,
                          IDP_VP7_MIDDLE_BUFFER_WIDTH,
                          IDP_VP7_MIDDLE_BUFFER_HEIGHT);
        }
        else
        {
          set_tv_output_data_format(TV_DATA_YUV420);
          // [MAUI_01656753][MAUI_02309461]
          set_tv_src_size(TV_OUT_OWNER_MP4_DEC,
                          video_src_width_with_dummy,
                          video_src_height_with_dummy);
        }
        
        video_decode_have_config_tvout = KAL_TRUE;
      }
    }
#endif
  }
  
  return KAL_TRUE;
}

kal_bool
idp_val_video_decode_memorymode_config(
    kal_uint32 const key,
    kal_uint32 const idp_int_addr,
    kal_uint32 const idp_int_size,
    kal_uint32 const idp_ext_addr,
    kal_uint32 const idp_ext_size,
    kal_uint32 const video_src_width_with_dummy,
    kal_uint32 const video_src_height_with_dummy,
    kal_uint32 const clip_left,
    kal_uint32 const clip_right,
    kal_uint32 const clip_top,
    kal_uint32 const clip_bottom,
    kal_bool   const b_quant,
    kal_uint32 const quant_addr,
    kal_bool   const FMT_4X4,
    MP4DEC_MEMMODE_STRUCT const * const data_input)
{
  kal_bool result;
  kal_uint32 dst_clip_x1;
  kal_uint32 dst_clip_x2;
  kal_uint32 dst_clip_y1;
  kal_uint32 dst_clip_y2;
  kal_uint32 video_target_width_with_dummy;
  kal_uint32 video_target_height_with_dummy;  
  kal_uint32 real_video_display_width; /* The display target width after rotation */
  kal_uint32 real_video_display_height; /* The display target height after rotation */
  kal_uint32 real_video_clip_left; /* the clip_left after resizing and rotation. */
  kal_uint32 real_video_clip_right; /* the clip_right after resizing and rotation. */ 
  kal_uint32 real_video_clip_top; /* the clip_top after resizing and rotation. */
  kal_uint32 real_video_clip_bottom; /* the clip_bottom after resizing and rotation. */
  kal_uint32 const src_clip_width = (clip_right - clip_left + 1);
  kal_uint32 const src_clip_height = (clip_bottom - clip_top + 1);
  kal_uint32 video_target_width_wo_dummy;
  kal_uint32 video_target_height_wo_dummy;
  
  ASSERT(clip_left <= clip_right);
  ASSERT(clip_top <= clip_bottom);
  ASSERT(clip_right < video_src_width_with_dummy);
  ASSERT(clip_bottom < video_src_height_with_dummy);

  // [MAUI_02601232] Block all video clips with src clipping size <= 15...
  if ((16 > src_clip_width) || (16 > src_clip_height))
  {
    return KAL_FALSE;
  }
  
  switch (data_input->rotate_angle)
  {
  case IMG_ROT_ANGLE_0:
  case IMG_ROT_ANGLE_180:
    video_target_width_wo_dummy = data_input->disp_width;
    video_target_height_wo_dummy = data_input->disp_height;
    break;
    
  case IMG_ROT_ANGLE_90:
  case IMG_ROT_ANGLE_270:
    video_target_width_wo_dummy = data_input->disp_height;
    video_target_height_wo_dummy = data_input->disp_width;
    break;
    
  default:
    ASSERT(0);
    video_target_width_wo_dummy = 0;
    video_target_height_wo_dummy = 0;
    break;
  }

  // [MAUI_01245490]
  video_target_width_with_dummy = (((kal_uint32)(video_target_width_wo_dummy) *
                                    (kal_uint32)(video_src_width_with_dummy) + 
                                    (kal_uint32)(src_clip_width) - 1) /
                                   (kal_uint32)(src_clip_width));
  video_target_height_with_dummy = (((kal_uint32)(video_target_height_wo_dummy) *
                                     (kal_uint32)(video_src_height_with_dummy) + 
                                     (kal_uint32)(src_clip_height) - 1) /
                                    (kal_uint32)(src_clip_height));
  
  for (;;)
  {
    src_clip_2_dst_clip_hori(data_input->rotate_angle,
                             video_src_width_with_dummy,
                             video_target_width_with_dummy,
                             clip_left,
                             clip_right,
                             &dst_clip_x1,
                             &dst_clip_x2);
    
    if ((dst_clip_x2 - dst_clip_x1 + 1) < video_target_width_wo_dummy)
    {
      ++video_target_width_with_dummy;
      continue;
    }
    else if ((dst_clip_x2 - dst_clip_x1 + 1) > video_target_width_wo_dummy)
    {
      dst_clip_x2 = (dst_clip_x1 + video_target_width_wo_dummy - 1);
      break;
    }
    else
    {
      break;
    }
  }
  
  for (;;)
  {
    src_clip_2_dst_clip_vert(data_input->rotate_angle,
                             video_src_height_with_dummy,
                             video_target_height_with_dummy,
                             clip_top,
                             clip_bottom,
                             &dst_clip_y1,
                             &dst_clip_y2);
    
    if ((dst_clip_y2 - dst_clip_y1 + 1) < video_target_height_wo_dummy)
    {
      ++video_target_height_with_dummy;
      continue;
    }
    else if ((dst_clip_y2 - dst_clip_y1 + 1) > video_target_height_wo_dummy)
    {
      dst_clip_y2 = (dst_clip_y1 + video_target_height_wo_dummy - 1);
      break;
    }
    else
    {
      break;
    }
  }
  
  switch (data_input->rotate_angle)
  {
  case IMG_ROT_ANGLE_0:
    real_video_display_width = video_target_width_with_dummy;
    real_video_display_height = video_target_height_with_dummy;
    real_video_clip_left = dst_clip_x1;
    real_video_clip_right = dst_clip_x2;
    real_video_clip_top = dst_clip_y1;
    real_video_clip_bottom = dst_clip_y2;
    break;
    
  case IMG_ROT_ANGLE_180:
    real_video_display_width = video_target_width_with_dummy;
    real_video_display_height = video_target_height_with_dummy;
    real_video_clip_left = (real_video_display_width - 1 - dst_clip_x2);
    real_video_clip_right = (real_video_display_width - 1 - dst_clip_x1);
    real_video_clip_top = (real_video_display_height - 1 - dst_clip_y2);
    real_video_clip_bottom = (real_video_display_height - 1 - dst_clip_y1);
    break;
    
  case IMG_ROT_ANGLE_90:
    real_video_display_width = video_target_height_with_dummy;
    real_video_display_height = video_target_width_with_dummy;
    real_video_clip_left = (real_video_display_width - 1 - dst_clip_y2);
    real_video_clip_right = (real_video_display_width - 1 - dst_clip_y1);
    real_video_clip_top = dst_clip_x1;
    real_video_clip_bottom = dst_clip_x2;
    break;
    
  case IMG_ROT_ANGLE_270:
    real_video_display_width = video_target_height_with_dummy;
    real_video_display_height = video_target_width_with_dummy;
    real_video_clip_left = dst_clip_y1;
    real_video_clip_right = dst_clip_y2;
    real_video_clip_top = (real_video_display_height - 1 - dst_clip_x2);
    real_video_clip_bottom = (real_video_display_height - 1 - dst_clip_x1);
    break;
    
  default:
    ASSERT(0);
    real_video_display_width = 0;
    real_video_display_height = 0;
    real_video_clip_left = 0;
    real_video_clip_right = 0;
    real_video_clip_top = 0;
    real_video_clip_bottom = 0; 
    break;
  }
  
  result = idp_video_decode_config(
      key,
    
      IDP_VIDEO_DECODE_INTMEM_START_ADDRESS, idp_int_addr,
      IDP_VIDEO_DECODE_INTMEM_SIZE, idp_int_size,
      IDP_VIDEO_DECODE_EXTMEM_START_ADDRESS, idp_ext_addr,
      IDP_VIDEO_DECODE_EXTMEM_SIZE, idp_ext_size,
    
      IDP_VIDEO_DECODE_SRC_WIDTH, video_src_width_with_dummy,
      IDP_VIDEO_DECODE_SRC_HEIGHT, video_src_height_with_dummy,
      IDP_VIDEO_DECODE_TARGET_WIDTH_FOR_TVOUT, real_video_display_width,
      IDP_VIDEO_DECODE_TARGET_HEIGHT_FOR_TVOUT, real_video_display_height,
      IDP_VIDEO_DECODE_TARGET_WIDTH, real_video_display_width,
      IDP_VIDEO_DECODE_TARGET_HEIGHT, real_video_display_height,
    
      IDP_VIDEO_DECODE_ENABLE_CLIP, KAL_TRUE,
      IDP_VIDEO_DECODE_CLIP_LEFT, real_video_clip_left,
      IDP_VIDEO_DECODE_CLIP_RIGHT, real_video_clip_right,
      IDP_VIDEO_DECODE_CLIP_TOP, real_video_clip_top,
      IDP_VIDEO_DECODE_CLIP_BOTTOM, real_video_clip_bottom,
    
      IDP_VIDEO_DECODE_CONTRAST_LEVEL, data_input->contrast_level,
      IDP_VIDEO_DECODE_BRIGHTNESS_LEVEL, data_input->brightness_level, 
      IDP_VIDEO_DECODE_VIDEO_Y_BUFFER_ADDRESS, 0,
      IDP_VIDEO_DECODE_VIDEO_U_BUFFER_ADDRESS, 0,
      IDP_VIDEO_DECODE_VIDEO_V_BUFFER_ADDRESS, 0,
      IDP_VIDEO_DECODE_ENABLE_PITCH, KAL_FALSE,
#if defined(DRV_MP4_DEC_SUPPORT)
      IDP_VIDEO_DECODE_IMAGE_DATA_FORMAT, data_input->image_data_format,
#endif
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS, data_input->lcd_buf_addr,
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS_2, 0,
      IDP_VIDEO_DECODE_TRIGGER_LCD, KAL_FALSE,
      IDP_VIDEO_DECODE_FORCE_LCD_HW_TRIGGER, KAL_FALSE,
    
      IDP_VIDEO_DECODE_ROT_ANGLE, data_input->rotate_angle,
      IDP_VIDEO_DECODE_SRC_FMT_4X4, FMT_4X4,
      IDP_VIDEO_DECODE_ENABLE_MP4DEBLK, b_quant,
      IDP_VIDEO_DECODE_MP4DEBLK_QUANT_BUF, quant_addr,
    
#if defined(__MTK_TARGET__)
      IDP_VIDEO_DECODE_RESIZER_U_VALUE, 8,
      IDP_VIDEO_DECODE_RESIZER_V_VALUE, 15,
#endif
    
      0);
  if (KAL_FALSE == result)
  {
    return KAL_FALSE;
  }

  g_idp_val_video_decode_is_vp7 = KAL_FALSE;
  
  {
    lcd_frame_update_struct lcd_data;
    
    memset(&lcd_data, 0, sizeof(lcd_data));
    
    // This path doesn't trigger LCD all the time.
    video_decode_trigger_lcd_this_time = KAL_FALSE;    
    
#if defined(TV_OUT_SUPPORT) && defined(DRV_MP4_V2)
    video_decode_trigger_tvout = data_input->tv_output;
    
    if ((KAL_TRUE == data_input->tv_output) &&
        ((TV_OUTPUT_MODE2 == tv_output_config_data.tv_output_mode) ||
         (TV_OUTPUT_MODE3 == tv_output_config_data.tv_output_mode)))
    {
      // TV output mode 2 & 3 don't use LCD, so that I have
      // to config it separatly.
      kal_uint16 tv_src_width = (kal_uint16)(real_video_clip_right-real_video_clip_left+1);
      kal_uint16 tv_src_height = (kal_uint16)(real_video_clip_bottom-real_video_clip_top+1);

      // TV output only receive even width/height when using RGB565...
      if ((KAL_FALSE == video_decode_have_config_tvout) && 
          (0x0 == (0x1&tv_src_width)) && 
          (0x0 == (0x1&tv_src_height)))
      {
        // Update tv output owner.
        tv_output_owner = TV_OUT_OWNER_MP4_DEC;

        // [MAUI_02309461]
        set_tv_output_data_format(TV_DATA_RGB565);
        // [MAUI_01656753]
        set_tv_src_size(TV_OUT_OWNER_MP4_DEC,
                        tv_src_width,
                        tv_src_height);
        
        video_decode_have_config_tvout = KAL_TRUE;
      }
    }
#endif
  }
  
  return KAL_TRUE;
}

kal_bool
idp_val_video_decode_memorymode_configurable(
    kal_uint32 const key,
    kal_uint32 const idp_int_addr,
    kal_uint32 const idp_int_size,
    kal_uint32 const idp_ext_addr,
    kal_uint32 const idp_ext_size,
    kal_uint32 const video_src_width_with_dummy,
    kal_uint32 const video_src_height_with_dummy,
    kal_uint32 const clip_left,
    kal_uint32 const clip_right,
    kal_uint32 const clip_top,
    kal_uint32 const clip_bottom,
    kal_bool   const b_quant,
    kal_uint32 const quant_addr,
    kal_bool   const FMT_4X4,
    MP4DEC_MEMMODE_STRUCT const * const data_input)
{
#if defined(__MTK_TARGET__)
  kal_bool result;
  kal_uint32 dst_clip_x1;
  kal_uint32 dst_clip_x2;
  kal_uint32 dst_clip_y1;
  kal_uint32 dst_clip_y2;
  kal_uint32 video_target_width_with_dummy;
  kal_uint32 video_target_height_with_dummy;  
  kal_uint32 real_video_display_width; /* The display target width after rotation */
  kal_uint32 real_video_display_height; /* The display target height after rotation */
  kal_uint32 real_video_clip_left; /* the clip_left after resizing and rotation. */
  kal_uint32 real_video_clip_right; /* the clip_right after resizing and rotation. */
  kal_uint32 real_video_clip_top; /* the clip_top after resizing and rotation. */
  kal_uint32 real_video_clip_bottom; /* the clip_bottom after resizing and rotation. */
  kal_uint32 const src_clip_width = (clip_right - clip_left + 1);
  kal_uint32 const src_clip_height = (clip_bottom - clip_top + 1);
  kal_uint32 video_target_width_wo_dummy;
  kal_uint32 video_target_height_wo_dummy;
  
  ASSERT(clip_left <= clip_right);
  ASSERT(clip_top <= clip_bottom);
  ASSERT(clip_right < video_src_width_with_dummy);
  ASSERT(clip_bottom < video_src_height_with_dummy);

  // [MAUI_02601232] Block all video clips with src clipping size <= 15...
  if ((16 > src_clip_width) || (16 > src_clip_height))
  {
    return KAL_FALSE;
  }
  
  switch (data_input->rotate_angle)
  {
  case IMG_ROT_ANGLE_0:
  case IMG_ROT_ANGLE_180:
    video_target_width_wo_dummy = data_input->disp_width;
    video_target_height_wo_dummy = data_input->disp_height;
    break;
    
  case IMG_ROT_ANGLE_90:
  case IMG_ROT_ANGLE_270:
    video_target_width_wo_dummy = data_input->disp_height;
    video_target_height_wo_dummy = data_input->disp_width;
    break;
    
  default:
    ASSERT(0);
    video_target_width_wo_dummy = 0;
    video_target_height_wo_dummy = 0;
    break;
  }

  // [MAUI_01245490]
  video_target_width_with_dummy = (((kal_uint32)(video_target_width_wo_dummy) *
                                    (kal_uint32)(video_src_width_with_dummy) + 
                                    (kal_uint32)(src_clip_width) - 1) /
                                   (kal_uint32)(src_clip_width));
  video_target_height_with_dummy = (((kal_uint32)(video_target_height_wo_dummy) *
                                     (kal_uint32)(video_src_height_with_dummy) +
                                     (kal_uint32)(src_clip_height) - 1) /
                                    (kal_uint32)(src_clip_height));
  
  for (;;)
  {
    src_clip_2_dst_clip_hori(data_input->rotate_angle,
                             video_src_width_with_dummy,
                             video_target_width_with_dummy,
                             clip_left,
                             clip_right,
                             &dst_clip_x1,
                             &dst_clip_x2);
    
    if ((dst_clip_x2 - dst_clip_x1 + 1) < video_target_width_wo_dummy)
    {
      ++video_target_width_with_dummy;
      continue;
    }
    else if ((dst_clip_x2 - dst_clip_x1 + 1) > video_target_width_wo_dummy)
    {
      dst_clip_x2 = (dst_clip_x1 + video_target_width_wo_dummy - 1);
      break;
    }
    else
    {
      break;
    }
  }
  
  for (;;)
  {
    src_clip_2_dst_clip_vert(data_input->rotate_angle,
                             video_src_height_with_dummy,
                             video_target_height_with_dummy,
                             clip_top,
                             clip_bottom,
                             &dst_clip_y1,
                             &dst_clip_y2);
    
    if ((dst_clip_y2 - dst_clip_y1 + 1) < video_target_height_wo_dummy)
    {
      ++video_target_height_with_dummy;
      continue;
    }
    else if ((dst_clip_y2 - dst_clip_y1 + 1) > video_target_height_wo_dummy)
    {
      dst_clip_y2 = (dst_clip_y1 + video_target_height_wo_dummy - 1);
      break;
    }
    else
    {
      break;
    }
  }
  
  switch (data_input->rotate_angle)
  {
  case IMG_ROT_ANGLE_0:
    real_video_display_width = video_target_width_with_dummy;
    real_video_display_height = video_target_height_with_dummy;
    real_video_clip_left = dst_clip_x1;
    real_video_clip_right = dst_clip_x2;
    real_video_clip_top = dst_clip_y1;
    real_video_clip_bottom = dst_clip_y2;
    break;
    
  case IMG_ROT_ANGLE_180:
    real_video_display_width = video_target_width_with_dummy;
    real_video_display_height = video_target_height_with_dummy;
    real_video_clip_left = (real_video_display_width - 1 - dst_clip_x2);
    real_video_clip_right = (real_video_display_width - 1 - dst_clip_x1);
    real_video_clip_top = (real_video_display_height - 1 - dst_clip_y2);
    real_video_clip_bottom = (real_video_display_height - 1 - dst_clip_y1);
    break;
    
  case IMG_ROT_ANGLE_90:
    real_video_display_width = video_target_height_with_dummy;
    real_video_display_height = video_target_width_with_dummy;
    real_video_clip_left = (real_video_display_width - 1 - dst_clip_y2);
    real_video_clip_right = (real_video_display_width - 1 - dst_clip_y1);
    real_video_clip_top = dst_clip_x1;
    real_video_clip_bottom = dst_clip_x2;
    break;
    
  case IMG_ROT_ANGLE_270:
    real_video_display_width = video_target_height_with_dummy;
    real_video_display_height = video_target_width_with_dummy;
    real_video_clip_left = dst_clip_y1;
    real_video_clip_right = dst_clip_y2;
    real_video_clip_top = (real_video_display_height - 1 - dst_clip_x2);
    real_video_clip_bottom = (real_video_display_height - 1 - dst_clip_x1);
    break;
    
  default:
    ASSERT(0);
    real_video_display_width = 0;
    real_video_display_height = 0;
    real_video_clip_left = 0;
    real_video_clip_right = 0;
    real_video_clip_top = 0;
    real_video_clip_bottom = 0; 
    break;
  }
  
  result = idp_video_decode_configurable(
      key,
    
      IDP_VIDEO_DECODE_INTMEM_START_ADDRESS, idp_int_addr,
      IDP_VIDEO_DECODE_INTMEM_SIZE, idp_int_size,
      IDP_VIDEO_DECODE_EXTMEM_START_ADDRESS, idp_ext_addr,
      IDP_VIDEO_DECODE_EXTMEM_SIZE, idp_ext_size,
    
      IDP_VIDEO_DECODE_SRC_WIDTH, video_src_width_with_dummy,
      IDP_VIDEO_DECODE_SRC_HEIGHT, video_src_height_with_dummy,
      IDP_VIDEO_DECODE_TARGET_WIDTH_FOR_TVOUT, real_video_display_width,
      IDP_VIDEO_DECODE_TARGET_HEIGHT_FOR_TVOUT, real_video_display_height,
      IDP_VIDEO_DECODE_TARGET_WIDTH, real_video_display_width,
      IDP_VIDEO_DECODE_TARGET_HEIGHT, real_video_display_height,
    
      IDP_VIDEO_DECODE_ENABLE_CLIP, KAL_TRUE,
      IDP_VIDEO_DECODE_CLIP_LEFT, real_video_clip_left,
      IDP_VIDEO_DECODE_CLIP_RIGHT, real_video_clip_right,
      IDP_VIDEO_DECODE_CLIP_TOP, real_video_clip_top,
      IDP_VIDEO_DECODE_CLIP_BOTTOM, real_video_clip_bottom,
    
      IDP_VIDEO_DECODE_CONTRAST_LEVEL, data_input->contrast_level,
      IDP_VIDEO_DECODE_BRIGHTNESS_LEVEL, data_input->brightness_level, 
      IDP_VIDEO_DECODE_VIDEO_Y_BUFFER_ADDRESS, 0,
      IDP_VIDEO_DECODE_VIDEO_U_BUFFER_ADDRESS, 0,
      IDP_VIDEO_DECODE_VIDEO_V_BUFFER_ADDRESS, 0,
      IDP_VIDEO_DECODE_ENABLE_PITCH, KAL_FALSE,
#if defined(DRV_MP4_DEC_SUPPORT)
      IDP_VIDEO_DECODE_IMAGE_DATA_FORMAT, data_input->image_data_format,
#endif
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS, data_input->lcd_buf_addr,
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS_2, 0,
      IDP_VIDEO_DECODE_TRIGGER_LCD, KAL_FALSE,
      IDP_VIDEO_DECODE_FORCE_LCD_HW_TRIGGER, KAL_FALSE,
    
      IDP_VIDEO_DECODE_ROT_ANGLE, data_input->rotate_angle,
      IDP_VIDEO_DECODE_SRC_FMT_4X4, FMT_4X4,
      IDP_VIDEO_DECODE_ENABLE_MP4DEBLK, b_quant,
      IDP_VIDEO_DECODE_MP4DEBLK_QUANT_BUF, quant_addr,
    
#if defined(__MTK_TARGET__)
      IDP_VIDEO_DECODE_RESIZER_U_VALUE, 8,
      IDP_VIDEO_DECODE_RESIZER_V_VALUE, 15,
#endif
    
      0);
  if (KAL_FALSE == result)
  {
    return KAL_FALSE;
  }
  else
  {
    return KAL_TRUE;
  }
#else
  return KAL_TRUE;
#endif
}

kal_bool
idp_val_video_decode_set_yuv_address(
    kal_uint32 const key,
    kal_uint8 * const y_address,
    kal_uint8 * const u_address,
    kal_uint8 * const v_address)
{
  kal_bool result;
  
  result = idp_video_decode_config(
      key,
    
      IDP_VIDEO_DECODE_VIDEO_Y_BUFFER_ADDRESS, y_address,
      IDP_VIDEO_DECODE_VIDEO_U_BUFFER_ADDRESS, u_address,
      IDP_VIDEO_DECODE_VIDEO_V_BUFFER_ADDRESS, v_address,
    
      0);
  if (KAL_FALSE == result)
  {
    ASSERT(0);
  }
  
  return KAL_TRUE;
}

kal_bool
idp_val_video_decode_start_output_to_tv(kal_uint32 const rgb_address)
{
#ifdef TV_OUT_SUPPORT
  if ((KAL_TRUE == video_decode_trigger_tvout) && 
      (KAL_TRUE == video_decode_have_config_tvout))
  {
    if ((TV_OUTPUT_MODE2 == tv_output_config_data.tv_output_mode) ||
        (TV_OUTPUT_MODE3 == tv_output_config_data.tv_output_mode))
    {
      /* [MAUI_02309461] Remove the checking allow for VP7...
      if (KAL_FALSE == g_idp_val_video_decode_is_vp7)
      {
        ASSERT(0);
      }
       */ 
      
      // [MAUI_02309461] Add the checking for TVOUT color format...
      if (TV_DATA_RGB565 == tv_output_config_data.tv_output_data_format)
      {
        tv_fb_update(TV_OUT_OWNER_MP4_DEC, rgb_address);
      }
    }
  }
#endif
  
  return KAL_TRUE;
}

kal_bool
idp_val_video_decode_restart_all(kal_uint32 const key)
{
  kal_bool result;
  
  result = idp_video_decode_stop(key);
  if (KAL_FALSE == result)
  {
    ASSERT(0);
  }
  
#ifdef TV_OUT_SUPPORT
  if (KAL_TRUE == video_decode_trigger_tvout)
  {
    // MDP or Video Codec output will be directly read by TVOUT...
    if ((TV_OUTPUT_MODE2 == tv_output_config_data.tv_output_mode) ||
        (TV_OUTPUT_MODE3 == tv_output_config_data.tv_output_mode))
    {
      kal_uint32 y_buffer_addr;
      kal_uint32 u_buffer_addr;
      kal_uint32 v_buffer_addr;
      
      result = idp_video_decode_query(
          key,
          IDP_VIDEO_DECODE_QUERY_CURRENT_DECODABLE_VIDEO_YUV_BUFFER_ADDR,
          &y_buffer_addr, &u_buffer_addr, &v_buffer_addr,
          0);

      if (KAL_FALSE == result)
      {
        ASSERT(0);
      }
      
      // [MAUI_02309461]
      if ((KAL_FALSE == g_idp_val_video_decode_is_vp7) && 
          (TV_DATA_YUV420 == tv_output_config_data.tv_output_data_format))
      {
        tv_fb_update_yuv420(TV_OUT_OWNER_MP4_DEC,
                            y_buffer_addr,
                            u_buffer_addr,
                            v_buffer_addr);
      }
    }
  }
#endif  // #ifdef TV_OUT_SUPPORT
  
  result = idp_video_decode_start_all(key);
  if (KAL_FALSE == result)
  {
    ASSERT(0);
  }
  
  return KAL_TRUE;
}

kal_bool
idp_val_video_decode_close(kal_uint32 const key)
{
  kal_bool result;
  
  result = idp_video_decode_close(key);
  if (KAL_FALSE == result)
  {
    ASSERT(0);
  }
  
#if defined(TV_OUT_SUPPORT) && defined(__MTK_TARGET__)
  tv_reset();
  video_decode_have_config_tvout = KAL_FALSE;
#endif
  
  if (KAL_TRUE == video_decode_trigger_lcd_this_time)
  {
    lcd_stop_hw_update(video_decode_triggered_lcd_id_this_time);
    video_decode_have_config_lcd = KAL_FALSE;
  }
  
  return KAL_TRUE;
}

#endif // DRV_IDP_6238_SERIES

#if defined(DRV_IDP_MT6236_SERIES)

static kal_bool _idp_val_vp_have_config_lcd = KAL_FALSE;
static kal_bool _idp_val_vp_trigger_lcd_this_time = KAL_FALSE;
static kal_uint32 _idp_val_vp_triggered_lcd_id_this_time = 0;

/**
 *  @todo XX
 */
kal_bool
idp_val_video_decode_configurable(kal_uint32 const key,
                                  kal_uint32 const idp_int_addr,
                                  kal_uint32 const idp_int_size,
                                  kal_uint32 const idp_ext_addr,
                                  kal_uint32 const idp_ext_size,
                                  kal_uint32 const video_src_width_with_dummy,
                                  kal_uint32 const video_src_height_with_dummy,
                                  kal_uint32 const clip_left,
                                  kal_uint32 const clip_right,
                                  kal_uint32 const clip_top,
                                  kal_uint32 const clip_bottom,
                                  kal_uint32 const y_address,
                                  kal_uint32 const u_address,
                                  kal_uint32 const v_address,
                                  kal_bool   const b_quant,
                                  kal_uint32 const quant_addr,
                                  kal_bool   const FMT_4X4,
                                  MP4DEC_IMGPATH_STRUCT const * const data_input)
{
  return KAL_TRUE;
}

/**
 *  @todo OK
 */
kal_bool
idp_val_video_decode_config(kal_uint32 const key,
                            kal_uint32 const idp_int_addr,
                            kal_uint32 const idp_int_size,
                            kal_uint32 const idp_ext_addr,
                            kal_uint32 const idp_ext_size,
                            kal_uint32 const video_src_width_with_dummy,
                            kal_uint32 const video_src_height_with_dummy,
                            kal_uint32 const clip_left,
                            kal_uint32 const clip_right,
                            kal_uint32 const clip_top,
                            kal_uint32 const clip_bottom,
                            kal_uint32 const y_address,
                            kal_uint32 const u_address,
                            kal_uint32 const v_address,
                            kal_bool   const b_quant,
                            kal_uint32 const quant_addr,
                            kal_bool   const FMT_4X4,
                            MP4DEC_IMGPATH_STRUCT const * const data_input)
{
#if defined(__MTK_TARGET__)
  kal_bool result;

  // the display width is the result of rotation...
  kal_uint32 target_width = data_input->disp_width;
  kal_uint32 target_height = data_input->disp_height;

#if defined(SW_VIDEO_MT6236_HQA)
  if ((IMG_ROT_ANGLE_90 == data_input->rotate_angle) || 
      (IMG_ROT_ANGLE_270 == data_input->rotate_angle))
  {
    target_width = data_input->disp_height;
    target_height = data_input->disp_width;
  }
#endif // #if defined(SW_VIDEO_MT6236_HQA)
  
  result = idp_video_decode_config(
      key,

      /* not in use */
      IDP_VIDEO_DECODE_INTMEM_START_ADDRESS, 0,
      IDP_VIDEO_DECODE_INTMEM_SIZE, 0,
      IDP_VIDEO_DECODE_EXTMEM_START_ADDRESS, 0,
      IDP_VIDEO_DECODE_EXTMEM_SIZE, 0,
    
      IDP_VIDEO_DECODE_SRC_WIDTH, video_src_width_with_dummy,
      IDP_VIDEO_DECODE_SRC_HEIGHT, video_src_height_with_dummy,

      /* not in use */
      IDP_VIDEO_DECODE_TARGET_WIDTH_FOR_TVOUT, 0,
      IDP_VIDEO_DECODE_TARGET_HEIGHT_FOR_TVOUT, 0,

      // TODO: check if the two param is for after or before rotation
      IDP_VIDEO_DECODE_TARGET_WIDTH, target_width,
      IDP_VIDEO_DECODE_TARGET_HEIGHT, target_height,
    
      IDP_VIDEO_DECODE_ENABLE_CLIP, KAL_TRUE,
      IDP_VIDEO_DECODE_CLIP_LEFT, clip_left,
      IDP_VIDEO_DECODE_CLIP_RIGHT, clip_right,
      IDP_VIDEO_DECODE_CLIP_TOP, clip_top,
      IDP_VIDEO_DECODE_CLIP_BOTTOM, clip_bottom,
    
      IDP_VIDEO_DECODE_CONTRAST_LEVEL, 0x80, //data_input->contrast_level,
      IDP_VIDEO_DECODE_BRIGHTNESS_LEVEL, 0x80, //data_input->brightness_level, 
      IDP_VIDEO_DECODE_VIDEO_Y_BUFFER_ADDRESS, y_address,
      IDP_VIDEO_DECODE_VIDEO_U_BUFFER_ADDRESS, u_address,
      IDP_VIDEO_DECODE_VIDEO_V_BUFFER_ADDRESS, v_address,
#if defined(DRV_MP4_DEC_SUPPORT)
      IDP_VIDEO_DECODE_ENABLE_PITCH, data_input->image_pitch_mode,
      IDP_VIDEO_DECODE_BG_IMAGE_WIDTH, data_input->image_pitch_bytes, 
      IDP_VIDEO_DECODE_IMAGE_DATA_FORMAT, IMG_COLOR_FMT_RGB565, //data_input->image_data_format, 
#endif // #if defined(DRV_MP4_DEC_SUPPORT)
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS, data_input->lcd_buf_addr,
#if defined(SW_VIDEO_MT6236_HQA)
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS_2, data_input->lcd_buf_addr_2,
#endif // #if defined(SW_VIDEO_MT6236_HQA)
      IDP_VIDEO_DECODE_TRIGGER_LCD, KAL_TRUE,
      IDP_VIDEO_DECODE_FORCE_LCD_HW_TRIGGER, data_input->force_lcd_hw_trigger,

#if defined(SW_VIDEO_MT6236_HQA)
      IDP_VIDEO_DECODE_ROT_ANGLE, data_input->rotate_angle,
#endif // #if defined(SW_VIDEO_MT6236_HQA)

      /* not in use. */
      IDP_VIDEO_DECODE_SRC_FMT_4X4, KAL_FALSE,
      IDP_VIDEO_DECODE_ENABLE_MP4DEBLK, KAL_FALSE,
      IDP_VIDEO_DECODE_MP4DEBLK_QUANT_BUF, 0,
      
      IDP_VIDEO_DECODE_RESIZER_U_VALUE, 8,
      IDP_VIDEO_DECODE_RESIZER_V_VALUE, 15,
    
      0);
  if (KAL_FALSE == result)
  {
    return KAL_FALSE;
  }

  // config LCD
  {
    lcd_frame_update_struct lcd_data;
    
    kal_mem_set(&lcd_data, 0x0, sizeof(lcd_data));
    
    // This path doesn't trigger LCD all the time.
    _idp_val_vp_trigger_lcd_this_time = KAL_TRUE;
    
    if (KAL_FALSE == _idp_val_vp_have_config_lcd)
    {
      _idp_val_vp_triggered_lcd_id_this_time = data_input->lcd_data->lcd_id;
      
      lcd_data.fb_update_mode = LCD_HW_TRIGGER_MODE;
      lcd_data.hw_trigger_src = 0; // ROTDMA0
      
      lcd_data.memory_output = KAL_FALSE;
      lcd_data.block_mode_flag = KAL_FALSE;
      lcd_data.lcd_block_mode_cb = NULL;
      
      lcd_data.module_id = data_input->lcd_data->module_id;
      lcd_data.lcd_id = data_input->lcd_data->lcd_id;
    
      lcd_data.lcm_start_x = data_input->lcd_data->lcm_start_x;
      lcd_data.lcm_start_y = data_input->lcd_data->lcm_start_y;
      lcd_data.lcm_end_x = data_input->lcd_data->lcm_end_x;
      lcd_data.lcm_end_y = data_input->lcd_data->lcm_end_y;
      
      lcd_data.roi_offset_x = data_input->lcd_data->roi_offset_x;
      lcd_data.roi_offset_y = data_input->lcd_data->roi_offset_y;
      
      lcd_data.update_layer = data_input->lcd_data->update_layer;
      lcd_data.hw_update_layer = data_input->lcd_data->hw_update_layer;
      
      lcd_data.roi_background_color = data_input->lcd_data->roi_background_color;
              
      // Config LCD and start updating.
      ASSERT(LCD_OK == lcd_fb_update(&lcd_data));
      
      _idp_val_vp_have_config_lcd = KAL_TRUE;
    }
  }
#endif // #if defined(__MTK_TARGET__)
  return KAL_TRUE;
}

/**
 *  @todo XX
 */
kal_bool
idp_val_video_decode_memorymode_configurable(
    kal_uint32 const key,
    kal_uint32 const idp_int_addr,
    kal_uint32 const idp_int_size,
    kal_uint32 const idp_ext_addr,
    kal_uint32 const idp_ext_size,
    kal_uint32 const video_src_width_with_dummy,
    kal_uint32 const video_src_height_with_dummy,
    kal_uint32 const clip_left,
    kal_uint32 const clip_right,
    kal_uint32 const clip_top,
    kal_uint32 const clip_bottom,
    kal_bool   const b_quant,
    kal_uint32 const quant_addr,
    kal_bool   const FMT_4X4,
    MP4DEC_MEMMODE_STRUCT const * const data_input)
{
  return KAL_TRUE;
}

/**
 *  @todo OK
 */
kal_bool
idp_val_video_decode_memorymode_config(
    kal_uint32 const key,
    kal_uint32 const idp_int_addr,
    kal_uint32 const idp_int_size,
    kal_uint32 const idp_ext_addr,
    kal_uint32 const idp_ext_size,
    kal_uint32 const video_src_width_with_dummy,
    kal_uint32 const video_src_height_with_dummy,
    kal_uint32 const clip_left,
    kal_uint32 const clip_right,
    kal_uint32 const clip_top,
    kal_uint32 const clip_bottom,
    kal_bool   const b_quant,
    kal_uint32 const quant_addr,
    kal_bool   const FMT_4X4,
    MP4DEC_MEMMODE_STRUCT const * const data_input)
{
#if defined(__MTK_TARGET__)
  kal_bool result;

  // the display width is the result of rotation...
  kal_uint32 target_width = data_input->disp_width;
  kal_uint32 target_height = data_input->disp_height;

#if defined(SW_VIDEO_MT6236_HQA)
  if ((IMG_ROT_ANGLE_90 == data_input->rotate_angle) || 
      (IMG_ROT_ANGLE_270 == data_input->rotate_angle))
  {
    target_width = data_input->disp_height;
    target_height = data_input->disp_width;
  }
#endif // #if defined(SW_VIDEO_MT6236_HQA)
  
  result = idp_video_decode_config(
      key,

      /* not in use */
      IDP_VIDEO_DECODE_INTMEM_START_ADDRESS, 0,
      IDP_VIDEO_DECODE_INTMEM_SIZE, 0,
      IDP_VIDEO_DECODE_EXTMEM_START_ADDRESS, 0,
      IDP_VIDEO_DECODE_EXTMEM_SIZE, 0,
    
      IDP_VIDEO_DECODE_SRC_WIDTH, video_src_width_with_dummy,
      IDP_VIDEO_DECODE_SRC_HEIGHT, video_src_height_with_dummy,

      /* not in use */
      IDP_VIDEO_DECODE_TARGET_WIDTH_FOR_TVOUT, 0,
      IDP_VIDEO_DECODE_TARGET_HEIGHT_FOR_TVOUT, 0,
      
      IDP_VIDEO_DECODE_TARGET_WIDTH, target_width,
      IDP_VIDEO_DECODE_TARGET_HEIGHT, target_height,
    
      IDP_VIDEO_DECODE_ENABLE_CLIP, KAL_TRUE,
      IDP_VIDEO_DECODE_CLIP_LEFT, clip_left,
      IDP_VIDEO_DECODE_CLIP_RIGHT, clip_right,
      IDP_VIDEO_DECODE_CLIP_TOP, clip_top,
      IDP_VIDEO_DECODE_CLIP_BOTTOM, clip_bottom,
    /* ---- SKY_MULTIMEDIA start ---- */
#if defined(__MMI_DSM_NEW__) && defined(__DSM_MEDIA_EXT_H264_ENCODE__)&& defined(__MTK_TARGET__)
      IDP_VIDEO_DECODE_CONTRAST_LEVEL, data_input->contrast_level,
      IDP_VIDEO_DECODE_BRIGHTNESS_LEVEL, data_input->brightness_level, 
#else
      IDP_VIDEO_DECODE_CONTRAST_LEVEL, 0x20, //data_input->contrast_level,
      IDP_VIDEO_DECODE_BRIGHTNESS_LEVEL, 0x20, //data_input->brightness_level, 
#endif
/* ---- SKY_MULTIMEDIA end ---- */
      IDP_VIDEO_DECODE_VIDEO_Y_BUFFER_ADDRESS, 0,
      IDP_VIDEO_DECODE_VIDEO_U_BUFFER_ADDRESS, 0,
      IDP_VIDEO_DECODE_VIDEO_V_BUFFER_ADDRESS, 0,
      IDP_VIDEO_DECODE_ENABLE_PITCH, KAL_FALSE,
#if defined(DRV_MP4_DEC_SUPPORT)
      IDP_VIDEO_DECODE_IMAGE_DATA_FORMAT, IMG_COLOR_FMT_RGB565, //data_input->image_data_format,
#endif // #if defined(DRV_MP4_DEC_SUPPORT)
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS, data_input->lcd_buf_addr,
      IDP_VIDEO_DECODE_FRAME_BUFFER_ADDRESS_2, 0,
      IDP_VIDEO_DECODE_TRIGGER_LCD, KAL_FALSE,
      IDP_VIDEO_DECODE_FORCE_LCD_HW_TRIGGER, KAL_FALSE,

#if defined(SW_VIDEO_MT6236_HQA)
      IDP_VIDEO_DECODE_ROT_ANGLE, data_input->rotate_angle,
#endif // #if defined(SW_VIDEO_MT6236_HQA)

      /* not in use */
      IDP_VIDEO_DECODE_SRC_FMT_4X4, KAL_FALSE,
      IDP_VIDEO_DECODE_ENABLE_MP4DEBLK, KAL_FALSE,
      IDP_VIDEO_DECODE_MP4DEBLK_QUANT_BUF, 0x0, 

      IDP_VIDEO_DECODE_RESIZER_U_VALUE, 8,
      IDP_VIDEO_DECODE_RESIZER_V_VALUE, 15,
    
      0);
  if (KAL_FALSE == result)
  {
    return KAL_FALSE;
  }

  // config LCD
  {
    // This path doesn't trigger LCD all the time.
    _idp_val_vp_trigger_lcd_this_time = KAL_FALSE;    
  }
#endif // #if defined(__MTK_TARGET__)

  return KAL_TRUE;
}

kal_bool
idp_val_video_decode_set_yuv_address(
    kal_uint32 const key,
    kal_uint8 * const y_address,
    kal_uint8 * const u_address,
    kal_uint8 * const v_address)
{
#if defined(__MTK_TARGET__)
  kal_bool result;
  
  result = idp_video_decode_config(
      key,
    
      IDP_VIDEO_DECODE_VIDEO_Y_BUFFER_ADDRESS, y_address,
      IDP_VIDEO_DECODE_VIDEO_U_BUFFER_ADDRESS, u_address,
      IDP_VIDEO_DECODE_VIDEO_V_BUFFER_ADDRESS, v_address,
    
      0);
  if (KAL_FALSE == result)
  {
    ASSERT(0);
  }

#endif // #if defined(__MTK_TARGET__)

  return KAL_TRUE;
}

/**
 *  @todo OK
 */
kal_bool
idp_val_video_decode_restart_all(kal_uint32 const key)
{
#if defined(__MTK_TARGET__)
  kal_bool result;
  
  result = idp_video_decode_stop(key);
  if (KAL_FALSE == result)
  {
    ASSERT(0);
  }

  result = idp_video_decode_start_all(key);
  if (KAL_FALSE == result)
  {
    ASSERT(0);
  }
#endif // #if defined(__MTK_TARGET__)

  return KAL_TRUE;
}

/**
 *  @todo OK
 */
kal_bool
idp_val_video_decode_close(kal_uint32 const key)
{
#if defined(__MTK_TARGET__)
  kal_bool result;
  
  result = idp_video_decode_close(key);
  if (KAL_FALSE == result)
  {
    ASSERT(0);
  }
    
  if (KAL_TRUE == _idp_val_vp_trigger_lcd_this_time)
  {
    lcd_stop_hw_update(_idp_val_vp_triggered_lcd_id_this_time);
    _idp_val_vp_have_config_lcd = KAL_FALSE;
  }
#endif // #if defined(__MTK_TARGET__)

  return KAL_TRUE;
}
#endif // #if defined(DRV_IDP_MT6236_SERIES)

#if defined(__VIDEO_EDITOR__)
/* =================================================
 *                Video editor decode
 * ================================================= */

static kal_bool video_editor_decode_have_config_lcd = KAL_FALSE;
static kal_bool video_editor_decode_trigger_lcd_this_time = KAL_FALSE;
static kal_uint32 video_editor_decode_triggered_lcd_id_this_time = 0;

kal_bool
idp_val_video_editor_decode_close(kal_uint32 const key)
{
#if defined(DRV_IDP_6238_SERIES)
  kal_bool result;
  
  result = idp_video_editor_decode_close(key);
  if (KAL_FALSE == result)
  {
    ASSERT(0);
  }
  
  if (KAL_TRUE == video_editor_decode_trigger_lcd_this_time)
  {
    lcd_stop_hw_update(video_editor_decode_triggered_lcd_id_this_time);
    video_editor_decode_have_config_lcd = KAL_FALSE;
  }
#endif // #if defined(DRV_IDP_6238_SERIES)  
  return KAL_TRUE;
}

kal_bool
idp_val_video_editor_decode_start_all(
    kal_uint32 const key,
    lcd_frame_update_to_mem_struct * const video_editor_lcd_data)
{
#if defined(DRV_IDP_6238_SERIES)
  kal_bool result;
  
  {
    lcd_frame_update_to_mem_struct lcd_para;
    
    video_editor_decode_trigger_lcd_this_time = KAL_TRUE;
    video_editor_decode_triggered_lcd_id_this_time = MAIN_LCD;
    
    memset(&lcd_para, 0, sizeof(lcd_para));
    
    {
#if defined(DRV_IDP_6238_SERIES)
      lcd_para.hw_trigger_src = LCD_HW_TRIGGER_IRT1;
#endif // #if defined(DRV_IDP_6238_SERIES)
      lcd_para.memory_data_format = LCD_WMEM_RGB565;
      lcd_para.fb_update_mode = LCD_HW_TRIGGER_MODE;
      lcd_para.dest_offset_x = 0;
      lcd_para.dest_offset_y = 0;
    }
    
    {
      lcd_para.block_mode = video_editor_lcd_data->block_mode;
      
      lcd_para.dest_block_width = video_editor_lcd_data->dest_block_width;
      lcd_para.dest_buffer_address = video_editor_lcd_data->dest_buffer_address;
      lcd_para.dest_buffer_size = video_editor_lcd_data->dest_buffer_size;
        
      lcd_para.roi_offset_x = video_editor_lcd_data->roi_offset_x;
      lcd_para.roi_offset_y = video_editor_lcd_data->roi_offset_y;
      lcd_para.roi_width = video_editor_lcd_data->roi_width;
      lcd_para.roi_height = video_editor_lcd_data->roi_height;
        
      lcd_para.update_layer = video_editor_lcd_data->update_layer;
      lcd_para.hw_update_layer = video_editor_lcd_data->hw_update_layer;
      
      lcd_para.roi_background_color = video_editor_lcd_data->roi_background_color;
    }
    
    lcd_fb_update_to_memory(&lcd_para);
  }
  
  result = idp_video_editor_decode_start_all(key);
  if (KAL_FALSE == result)
  {
    ASSERT(0);
  }
#endif // #if defined(DRV_IDP_6238_SERIES)
  return KAL_TRUE;
}

kal_bool
idp_val_video_editor_decode_config(
    kal_uint32 const key,
    kal_uint32 const idp_int_addr,
    kal_uint32 const idp_int_size,
    kal_uint32 const idp_ext_addr,
    kal_uint32 const idp_ext_size,
    video_editor_data_path_struct * const video_editor_data)
{
#if defined(DRV_IDP_6238_SERIES)
  kal_bool result;
  
  result = idp_video_editor_decode_config(
      key,
    
      IDP_VIDEO_EDITOR_DECODE_INTMEM_START_ADDRESS, idp_int_addr,
      IDP_VIDEO_EDITOR_DECODE_INTMEM_SIZE, idp_int_size,
      IDP_VIDEO_EDITOR_DECODE_EXTMEM_START_ADDRESS, idp_ext_addr,
      IDP_VIDEO_EDITOR_DECODE_EXTMEM_SIZE, idp_ext_size,
    
      IDP_VIDEO_EDITOR_DECODE_VIDEO_SRC_WIDTH, video_editor_data->video_src_width,
      IDP_VIDEO_EDITOR_DECODE_VIDEO_SRC_HEIGHT, video_editor_data->video_src_height,
      IDP_VIDEO_EDITOR_DECODE_VIDEO_TAR_WIDTH, video_editor_data->video_tar_width,
      IDP_VIDEO_EDITOR_DECODE_VIDEO_TAR_HEIGHT, video_editor_data->video_tar_height,
    
      IDP_VIDEO_EDITOR_DECODE_SOURCE_VIDEO_Y_BUFFER_ADDRESS, video_editor_data->source_video_y_buffer_address,
      IDP_VIDEO_EDITOR_DECODE_SOURCE_VIDEO_U_BUFFER_ADDRESS, video_editor_data->source_video_u_buffer_address,
      IDP_VIDEO_EDITOR_DECODE_SOURCE_VIDEO_V_BUFFER_ADDRESS, video_editor_data->source_video_v_buffer_address,
    
      IDP_VIDEO_EDITOR_DECODE_DST_BUFFER_ADDRESS, video_editor_data->lcd_buffer_address,
    
      IDP_VIDEO_EDITOR_DECODE_ROT_ANGLE, IMG_ROT_ANGLE_0,
    
      0);
  ASSERT(KAL_TRUE == result);
#endif // #if defined(DRV_IDP_6238_SERIES)
  return KAL_TRUE;
}

/* =================================================
 *                Video editor encode
 * ================================================= */

kal_bool
idp_val_video_editor_encode_config(
    kal_uint32 const key,
    kal_uint32 const idp_int_addr,
    kal_uint32 const idp_int_size,
    kal_uint32 const idp_ext_addr,
    kal_uint32 const idp_ext_size,
    video_editor_data_path_struct * const video_editor_data)
{
#if defined(DRV_IDP_6238_SERIES)
  kal_bool result;
  
  result = idp_video_editor_encode_config(
      key,
    
      IDP_VIDEO_EDITOR_ENCODE_INTMEM_START_ADDRESS, idp_int_addr,
      IDP_VIDEO_EDITOR_ENCODE_INTMEM_SIZE, idp_int_size,
      IDP_VIDEO_EDITOR_ENCODE_EXTMEM_START_ADDRESS, idp_ext_addr,
      IDP_VIDEO_EDITOR_ENCODE_EXTMEM_SIZE, idp_ext_size,
    
      IDP_VIDEO_EDITOR_ENCODE_VIDEO_SRC_WIDTH, video_editor_data->video_tar_width,
      IDP_VIDEO_EDITOR_ENCODE_VIDEO_SRC_HEIGHT, video_editor_data->video_tar_height,
    
      IDP_VIDEO_EDITOR_ENCODE_TARGET_VIDEO_Y_BUFFER_ADDRESS, video_editor_data->target_video_y_buffer_address,
      IDP_VIDEO_EDITOR_ENCODE_TARGET_VIDEO_U_BUFFER_ADDRESS, video_editor_data->target_video_u_buffer_address,
      IDP_VIDEO_EDITOR_ENCODE_TARGET_VIDEO_V_BUFFER_ADDRESS, video_editor_data->target_video_v_buffer_address,
    
      IDP_VIDEO_EDITOR_ENCODE_LCD_BUFFER_ADDRESS, video_editor_data->lcd_buffer_address,
    
      IDP_VIDEO_EDITOR_ENCODE_ENCODE_DONE_CB, video_editor_data->video_cb,
      IDP_VIDEO_EDITOR_ENCODE_ENCODE_DONE_CB_PARAM, 0,
    
      0);
  ASSERT(KAL_TRUE == result);
#endif // #if defined(DRV_IDP_6238_SERIES)
  return KAL_TRUE;
}

#endif // #if defined(__VIDEO_EDITOR__)

/* =================================================
 *              Video Call Decode
 * ================================================= */

#if defined(__MEDIA_VT__)
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#if defined(__MTK_TARGET__)
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#endif
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#if defined(__MTK_TARGET__)
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#endif
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#if defined(__MTK_TARGET__)
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#endif
/* under construction !*/
/* under construction !*/
/* under construction !*/
#endif // #if defined(__MEDIA_VT__)

#endif // #if !defined(DRV_IDP_OLD_DESIGN)

